home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1999 March / EnigmA AMIGA RUN 35 (1999)(G.R. Edizioni)(IT)[!][issue 1999-03].iso / earcd / devel / vbcc-src / pp.c < prev    next >
C/C++ Source or Header  |  1999-01-01  |  20KB  |  976 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <assert.h>
  6.  
  7. FILE *infile;
  8. int line=1;
  9.  
  10. #define INCSIZE 16
  11. FILE **incfile;
  12. char **incname;
  13. int *incline;
  14. int incn,incsize;
  15.  
  16. #define PP_TSIZE 1024
  17.  
  18. /*FIXME*/
  19. #define ierror(x) abort();
  20. #define mymalloc(x) malloc(x)
  21. #define myrealloc(x,y) realloc(x,y)
  22.  
  23. /* must not collide with source character-set */
  24. enum {
  25.   TKKEYWORD=-32,
  26.   TKMARG,
  27.   TKIDENTIFIER,
  28.   TKNUMBER,
  29.   TKPLUSPLUS,
  30.   TKMINMIN,
  31.   TKEOL,
  32.   TKLTLT,
  33.   TKGTGT,
  34.   TKSREF,
  35.   TKLE,
  36.   TKGE,
  37.   TKEQ,
  38.   TKNE,
  39.   TKLAND,
  40.   TKLOR,
  41.   TKMULEQ,
  42.   TKDIVEQ,
  43.   TKMODEQ,
  44.   TKPLUSEQ,
  45.   TKMINEQ,
  46.   TKLTLTEQ,
  47.   TKGTGTEQ,
  48.   TKANDEQ,
  49.   TKOREQ,
  50.   TKXOREQ,
  51.   TKDDD,
  52.   TKNUMNUM
  53. };
  54.  
  55. static char *tokout[]={"err","err","err","err","++","--","","<<",">>","->","<=",">=","==",
  56.                "!=","&&","||","*=","/=","%=","+=","-=","<<=",">>=","&=",
  57.                "|=","^=","...","##"
  58. };
  59.  
  60. static char *desc[]={
  61.   "TKKEYWORD",
  62.   "TKMARG",
  63.   "TKIDENTIFIER",
  64.   "TKNUMBER",
  65.   "TKPLUSPLUS",
  66.   "TKMINMIN",
  67.   "TKEOL",
  68.   "TKLTLT",
  69.   "TKGTGT",
  70.   "TKSREF",
  71.   "TKLE",
  72.   "TKGE",
  73.   "TKEQ",
  74.   "TKNE",
  75.   "TKLAND",
  76.   "TKLOR",
  77.   "TKMULEQ",
  78.   "TKDIVEQ",
  79.   "TKMODEQ",
  80.   "TKPLUSEQ",
  81.   "TKMINEQ",
  82.   "TKLTLTEQ",
  83.   "TKGTGTEQ",
  84.   "TKANDEQ",
  85.   "TKOREQ",
  86.   "TKXOREQ",
  87.   "TKDDD",
  88.   "TKNUMNUM"
  89. };
  90.  
  91. typedef struct {
  92.   int size;
  93.   int next;
  94.   int *tokens;
  95. } tokenlist;
  96.  
  97. #ifndef OBFUSCATOR
  98.  
  99. #define VARARG_MACRO  1
  100. #define BUILTIN_MACRO 2
  101. #define NEED_PAREN    4
  102.  
  103. typedef struct {
  104.   char *name;
  105.   int flags;
  106.   int nargs;
  107.   tokenlist repl;
  108. } macro;
  109.  
  110. #define PP_HSIZE 16384
  111. static int **hash_table;
  112.  
  113. #define PP_MSIZE 128
  114. static macro *macro_table;
  115. static int macro_cnt=1,macro_size;
  116.  
  117. void print_tokenlist(FILE *,tokenlist *);
  118.  
  119. static void copy_tokenlist(tokenlist *new,tokenlist *old)
  120. {
  121.   if(new->size<old->next+new->next){
  122.     new->size=old->next+new->next;
  123.     new->tokens=myrealloc(new->tokens,new->size*sizeof(*new->tokens));
  124.   }
  125.   memcpy(new->tokens+new->next,old->tokens,old->next*sizeof(*new->tokens));
  126.   new->next+=old->next;
  127. }
  128.  
  129. static int new_macro(char *name,int flags,int nargs,tokenlist *repl)
  130. {
  131.   int i,*p;
  132.   if(macro_cnt>=macro_size){
  133.     macro_size+=PP_MSIZE;
  134.     macro_table=myrealloc(macro_table,macro_size*sizeof(*macro_table));
  135.     macro_table[0].name=0; /* dummy */
  136.   }
  137.   macro_table[macro_cnt].name=mymalloc(strlen(name)+1);
  138.   strcpy(macro_table[macro_cnt].name,name);
  139.   macro_table[macro_cnt].flags=flags;
  140.   macro_table[macro_cnt].nargs=nargs;
  141.   macro_table[macro_cnt].repl.size=0;
  142.   macro_table[macro_cnt].repl.next=0;
  143.   macro_table[macro_cnt].repl.tokens=0;  
  144.   copy_tokenlist(¯o_table[macro_cnt].repl,repl);
  145.   return macro_cnt++;
  146. }
  147.  
  148. static void free_macro(int n)
  149. {
  150.   free(macro_table[n].name);
  151.   free(macro_table[n].repl.tokens);
  152.   macro_table[n].name=0;
  153. }
  154.  
  155. static int hash(char *p)
  156. {
  157.   int s=0;
  158.   while(*p)
  159.     s+=*p++;
  160.   return s%PP_HSIZE;
  161. }
  162.  
  163. static int find_macro(char *name)
  164. {
  165.   int i=hash(name),n,*p;
  166.   if(!(p=hash_table[i])) return 0;
  167.   n=p[0];
  168.   for(i=1;i<=n;i++)
  169.     if(macro_table[p[i]].name&&!strcmp(macro_table[p[i]].name,name))
  170.       return p[i];
  171.   return 0;
  172. }
  173.  
  174. static void add_macro(int n)
  175. {
  176.   int i=hash(macro_table[n].name),*p;
  177.   if(!(p=hash_table[i])){
  178.     hash_table[i]=p=mymalloc(2*sizeof(*hash_table[i]));
  179.     p[0]=1;
  180.     p[1]=n;
  181.   }else{
  182.     p=hash_table[i]=myrealloc(p,(p[0]+1)*sizeof(*p));
  183.     p[0]++;
  184.     p[p[0]]=n;
  185. printf("hash_collisio, depth=%d\n",p[0]);
  186.   }
  187. }
  188.  
  189. #endif /* OBFUSCATOR */
  190.  
  191. static FILE *include_file(const char *name)
  192. {
  193.     if(incn>=incsize){
  194.     incsize+=INCSIZE;
  195.     incfile=myrealloc(incfile,incsize*sizeof(*incfile));
  196.     incname=myrealloc(incname,incsize*sizeof(*incname));
  197.     incline=myrealloc(incline,incsize*sizeof(*incline));
  198.     }
  199.     if(!name){
  200.     incfile[incn]=stdin;
  201.     name="<stdin>";
  202.     }else{
  203.     incfile[incn]=fopen(name,"r");
  204.     }
  205. printf("include file %s\n",name);
  206.     incname[incn]=mymalloc(strlen(name)+1);
  207.     strcpy(incname[incn],name);
  208.     incn++;
  209.     return incfile[incn-1];
  210. }
  211.  
  212. static FILE *close_file(void)
  213. {
  214.     --incn;
  215.     free(incname[incn]);
  216.     if(incfile[incn])
  217.       fclose(incfile[incn]);
  218.     if(incn<=0)
  219.     return 0;
  220.     return incfile[incn-1];
  221. }
  222.  
  223. static void add_token(tokenlist *p,int c)
  224. {
  225.   if(p->next>=p->size){
  226.     p->size+=PP_TSIZE;
  227.     p->tokens=myrealloc(p->tokens,p->size*sizeof(*p->tokens));
  228.   }
  229.   p->tokens[p->next]=c;
  230.   p->next++;
  231. }
  232.  
  233. int read_char(void)
  234. /* Read next input character. Counts line numbers. */
  235. {
  236.   int tmp=getc(infile);
  237.   if(tmp=='\n') line++;
  238.   return tmp;
  239. }
  240.  
  241. static int push_back=EOF;
  242.  
  243. static int get_next_char(void)
  244. /* Read next character. Handles trigraphs and line-concatenation. */
  245. {
  246.   static int buf[2],inbuf;
  247.   int tmp,tmp2;
  248.   if(push_back!=EOF){
  249.     tmp=push_back;
  250.     push_back=EOF;
  251.     return tmp;
  252.   }
  253.   if(inbuf==0){
  254.     tmp=read_char();
  255.     if(tmp!='\\'&&tmp!='?'){
  256.       return tmp;
  257.     }else{
  258.       buf[0]=tmp;
  259.       inbuf=1;
  260.       /* fall through */
  261.     }
  262.   }
  263.   if(inbuf==1){
  264.     if(buf[0]!='?'&&buf[0]!='\\'){
  265.       inbuf=0;
  266.       return buf[0];
  267.     }else{
  268.       tmp=read_char();
  269.       if(buf[0]=='\\'){
  270.     if(tmp=='\n'){
  271.       inbuf=0;
  272.       return get_next_char();
  273.     }else{
  274.       buf[0]=tmp;
  275.       return '\\';
  276.     }
  277.       }else{
  278.     if(tmp=='?'){
  279.       buf[1]='?';
  280.       inbuf=2;
  281.       /* fall through */
  282.     }else{
  283.       buf[0]=tmp;
  284.       return '?';
  285.     }
  286.       }
  287.     }
  288.   }
  289.   if(inbuf==2){
  290.     if(buf[0]!='?') ierror(0);
  291.     if(buf[1]!='?'){
  292.       inbuf=1;
  293.       tmp=buf[0];
  294.       buf[0]=buf[1];
  295.       return tmp;
  296.     }else{
  297.       tmp2=tmp=read_char();;
  298.       /* FIXME: only if on */
  299.       if(tmp=='=') tmp2='#';
  300.       else if(tmp=='(') tmp2='[';
  301.       else if(tmp=='/') tmp2='\\';
  302.       else if(tmp==')') tmp2=']';
  303.       else if(tmp=='\'') tmp2='^';
  304.       else if(tmp=='<') tmp2='{';
  305.       else if(tmp=='!') tmp2='|';
  306.       else if(tmp=='>') tmp2='}';
  307.       else if(tmp=='-') tmp2='~';
  308.       if(tmp!=tmp2){
  309.     /* FIXME: warning */
  310.     if(tmp2!='\\'){
  311.       inbuf=0;
  312.       return tmp2;
  313.     }else{
  314.       inbuf=1;
  315.       buf[0]=tmp2;
  316.       return get_next_char();
  317.     }
  318.       }else{
  319.     tmp=buf[0];
  320.     buf[0]=buf[1];
  321.     buf[1]=tmp2;
  322.     return tmp;
  323.       }
  324.     }
  325.   }
  326.   ierror(0);
  327. }
  328.  
  329. static int get_next_token(tokenlist *p)
  330. {
  331.   int c,z,tmp,*cnt;
  332.   while(1){
  333.     c=get_next_char();
  334.     if(c=='"'||c=='\''){
  335.       int term=c,escape=0;
  336.       add_token(p,c);      
  337.       z=p->next;
  338.       add_token(p,0);
  339.       while(1){
  340.     c=get_next_char();
  341.     /* FIXME */
  342.     if(c==EOF||c=='\n'){
  343.       puts("unterminated string");
  344.       return 0;
  345.     }
  346.     if(c==term&&!escape) return 0;
  347.     if(escape&&c=='\\')
  348.         escape=0;
  349.     else
  350.         escape=(c=='\\');
  351.     add_token(p,c);
  352.     p->tokens[z]++;
  353.       }
  354.     }else if(c=='_'||isalpha((unsigned char)c)){
  355.       add_token(p,TKIDENTIFIER);
  356.       z=p->next;
  357.       add_token(p,1);
  358.       add_token(p,c);
  359.       while((c=get_next_char())=='_'||isalnum((unsigned char)c)){
  360.     add_token(p,c);
  361.     p->tokens[z]++;
  362.       }
  363.       push_back=c;
  364.       return 0;
  365.     }else if(isdigit((unsigned char)c)){
  366.       tmp=c;
  367.       c=TKNUMBER;
  368.     }else if(c=='.'){
  369.       tmp=get_next_char();
  370.       if(isdigit((unsigned char)tmp)){
  371.     push_back=tmp;
  372.     tmp='.';
  373.     c=TKNUMBER;
  374.       }else if(tmp=='.'){
  375.     c=get_next_char();
  376.     if(c!='.'){puts("..x-token");return 0;}/*FIXME*/
  377.     add_token(p,TKDDD);
  378.     return 0;
  379.       }else
  380.     push_back=tmp;
  381.       /* fall through */
  382.     }else if(c=='+'){
  383.       c=get_next_char();
  384.       if(c=='+'){
  385.     add_token(p,TKPLUSPLUS);
  386.       }else if(c=='='){
  387.     add_token(p,TKPLUSEQ);
  388.       }else{
  389.     add_token(p,'+');
  390.     push_back=c;
  391.       }
  392.       return 0;
  393.     }else if(c=='-'){
  394.       c=get_next_char();
  395.       if(c=='-'){
  396.     add_token(p,TKMINMIN);
  397.       }else if(c=='='){
  398.     add_token(p,TKMINEQ);
  399.       }else if(c=='>'){
  400.     add_token(p,TKSREF);
  401.       }else{
  402.     add_token(p,'-');
  403.     push_back=c;
  404.       }
  405.       return 0;
  406.     }else if(c=='|'){
  407.       c=get_next_char();
  408.       if(c=='|'){
  409.     add_token(p,TKLOR);
  410.       }else if(c=='='){
  411.     add_token(p,TKOREQ);
  412.       }else{
  413.     add_token(p,'|');
  414.     push_back=c;
  415.       }
  416.       return 0;
  417.     }else if(c=='&'){
  418.       c=get_next_char();
  419.       if(c=='&'){
  420.     add_token(p,TKLAND);
  421.       }else if(c=='='){
  422.     add_token(p,TKANDEQ);
  423.       }else{
  424.     add_token(p,'&');
  425.     push_back=c;
  426.       }
  427.       return 0;
  428.     }else if(c=='<'){
  429.       c=get_next_char();
  430.       if(c=='<'){
  431.     c=get_next_char();
  432.     if(c=='='){
  433.       add_token(p,TKLTLTEQ);
  434.     }else{
  435.       add_token(p,TKLTLT);
  436.       push_back=c;
  437.     }
  438.       }else if(c=='='){
  439.     add_token(p,TKLE);
  440.       }else{
  441.     add_token(p,'<');
  442.     push_back=c;
  443.       }
  444.       return 0;
  445.     }else if(c=='>'){
  446.       c=get_next_char();
  447.       if(c=='>'){
  448.     c=get_next_char();
  449.     if(c=='=')
  450.       add_token(p,TKGTGTEQ);
  451.     else{
  452.       add_token(p,TKGTGT);
  453.       push_back=c;
  454.     }
  455.       }else if(c=='='){
  456.     add_token(p,TKGE);
  457.       }else{
  458.     add_token(p,'>');
  459.     push_back=c;
  460.       }
  461.       return 0;
  462.     }else if(c=='!'){
  463.       c=get_next_char();
  464.       if(c=='='){
  465.     add_token(p,TKNE);
  466.       }else{
  467.     add_token(p,'!');
  468.     push_back=c;
  469.       }
  470.       return 0;
  471.     }else if(c=='*'){
  472.       c=get_next_char();
  473.       if(c=='='){
  474.     add_token(p,TKMULEQ);
  475.       }else{
  476.     add_token(p,'*');
  477.     push_back=c;
  478.       }
  479.       return 0;
  480.     }else if(c=='%'){
  481.       c=get_next_char();
  482.       if(c=='='){
  483.     add_token(p,TKMODEQ);
  484.       }else{
  485.     add_token(p,'%');
  486.     push_back=c;
  487.       }
  488.       return 0;
  489.     }else if(c=='#'){
  490.       c=get_next_char();
  491.       if(c=='#'){
  492.     add_token(p,TKNUMNUM);
  493.       }else{
  494.     add_token(p,'#');
  495.     push_back=c;
  496.       }
  497.       return 0;
  498.     }else if(c=='/'){
  499.       /*FIXME*/
  500.       c=get_next_char();
  501.       if(c=='*'){
  502.     int cstate=0;
  503.     while(1){
  504.       c=get_next_char();
  505.       if(c=='*'){
  506.         if(cstate==2) /*FIXME*/;
  507.         cstate=1;
  508.       }else if(c=='/'){
  509.         if(cstate==1) break;
  510.         cstate=2;
  511.       }else cstate=0;
  512.     }
  513.     if(p->next>=1&&p->tokens[p->next-1]!=' '){
  514.         add_token(p,' ');
  515.         return 0;
  516.     }else
  517.         continue;
  518.       }else if(c=='/'/*FIXME*/){
  519.     while((c=get_next_char())!=EOF&&c!='\n');
  520.     if(c==EOF) ierror(0); /*FIXME*/
  521.     add_token(p,'\n');
  522.     return 0;
  523.       }else if(c=='='){
  524.     add_token(p,TKDIVEQ);
  525.     return 0;
  526.       }
  527.       push_back=c;
  528.       c='/';
  529.       /* fall through */
  530.     }
  531.     if(c==TKNUMBER){
  532.       add_token(p,TKNUMBER);
  533.       z=p->next;
  534.       add_token(p,1);
  535.       add_token(p,tmp);
  536.       while(1){
  537.     c=get_next_char();
  538.     if(c=='e'||c=='E'||/*FIXME?*/c=='p'||c=='P'){
  539.       add_token(p,c);
  540.       p->tokens[z]++;
  541.       tmp=get_next_char();
  542.       if(tmp=='+'||tmp=='-'){
  543.         add_token(p,tmp);
  544.         p->tokens[z]++;
  545.       }else{
  546.         push_back=tmp;
  547.       }
  548.     }else if(c=='.'||c=='_'||isalnum((unsigned char)c)){
  549.       add_token(p,c);
  550.       p->tokens[z]++;
  551.     }else{
  552.       push_back=c;
  553.       break;
  554.     }
  555.       }
  556.       return 0;
  557.     }
  558.     if(c==EOF||c=='\n'){
  559.       add_token(p,c);
  560.       return c;
  561.     }
  562.     if(!isspace((unsigned char)c)){
  563.       add_token(p,c);
  564.       return 0;
  565.     }else{
  566.       if(p->next>=1&&p->tokens[p->next-1]!=' ')
  567.     add_token(p,' ');
  568.       return 0;
  569.     }
  570.   }
  571. }
  572.  
  573. void print_tokenlist(FILE *f,tokenlist *p)
  574. {
  575.   int i,*tr=p->tokens,*end=tr+p->next;
  576.   while(tr<end){
  577.     if(*tr=='"'||*tr=='\''||*tr==TKIDENTIFIER||*tr==TKNUMBER){
  578.       int n;
  579.       if(*tr=='"')
  580.     fprintf(f,"STRING: ");
  581.       else if(*tr=='\'')
  582.     fprintf(f,"CCONST: ");
  583.       else if(*tr==TKNUMBER)
  584.     fprintf(f,"NUMBER: ");
  585.       else
  586.     fprintf(f,"IDENT: ");
  587.       tr++;
  588.       n=*tr++;
  589.       for(i=0;i<n;i++)
  590.     fprintf(f,"%c",*tr++);
  591.       fprintf(f,"\n");
  592.       continue;
  593.     }
  594.     if(*tr==TKMARG){
  595.       fprintf(f,"ARG %d\n",tr[1]);
  596.       tr+=2; continue;
  597.     }
  598.     if(*tr==EOF){
  599.       fprintf(f,"EOF\n");
  600.       tr++; continue;
  601.     }
  602.     if(*tr=='\n'){
  603.       fprintf(f,"NEWLINE\n");
  604.       tr++; continue;
  605.     }
  606.     if(*tr>=TKPLUSPLUS&&*tr<=TKNUMNUM){
  607.       fprintf(f,"%s\n",desc[*tr-TKKEYWORD]);
  608.       tr++; continue;
  609.     }
  610.     fprintf(f,"OTHER: %d(%c)\n",*tr,*tr);
  611.     tr++;
  612.   }
  613. }
  614.  
  615. void print_code(FILE *f,tokenlist *p)
  616. {
  617.   int i,*tr=p->tokens,*end=tr+p->next;
  618.   while(tr<end){
  619.     if(*tr=='"'||*tr=='\''||*tr==TKIDENTIFIER||*tr==TKNUMBER){
  620.       int n,c;
  621.       if(*tr==TKIDENTIFIER||*tr==TKNUMBER)
  622.     c=0;
  623.       else
  624.     c=*tr;
  625.       tr++;
  626.       if(c)
  627.       fprintf(f,"%c",c);
  628.       n=*tr++;
  629.       for(i=0;i<n;i++)
  630.     fprintf(f,"%c",*tr++);
  631.       if(c)
  632.     fprintf(f,"%c",c);
  633.       continue;
  634.     }
  635.     if(*tr==EOF){
  636.     return;
  637.     }
  638.     if(*tr=='\n'){
  639.       fprintf(f,"\n");
  640.       tr++; continue;
  641.     }
  642.     if(*tr>=TKPLUSPLUS&&*tr<=TKNUMNUM){
  643.       fprintf(f,"%s",tokout[*tr-TKKEYWORD]);
  644.       tr++; continue;
  645.     }
  646.     fprintf(f,"%c",*tr);
  647.     tr++;
  648.   }
  649. }
  650.  
  651. char *token2string(int *p)
  652. {
  653.   int n=p[1];char *s;
  654.   static char *buf,len;
  655.   if(n+1>len){
  656.     len=n+1;
  657.     buf=mymalloc(len);
  658.   }
  659.   s=buf;
  660.   p+=2;
  661.   while(--n>=0) *s++=*p++;
  662.   *s=0;
  663.   return buf;
  664. }
  665.  
  666. #ifndef OBFUSCATOR
  667.  
  668. static int *get_macro_arg(tokenlist *arg,int *p,int vararg)
  669. {
  670.   int par=0;
  671.   while(1){
  672.     if(*p==EOF||*p=='\n') puts("unterminated macro invocation"); /*FIXME*/
  673.     if(*p==','&&par==0&&!vararg) return p;
  674.     if(*p==')'){
  675.       if(par>0){
  676.     add_token(arg,*p++);
  677.     par--;
  678.     continue;
  679.       }else
  680.     return p;
  681.     }
  682.     if(*p==TKIDENTIFIER||*p==TKNUMBER||*p=='"'||*p=='\''){
  683.       int n;
  684.       add_token(arg,*p++);
  685.       n=*p;
  686.       add_token(arg,*p++);
  687.       while(--n>=0) add_token(arg,*p++);
  688.       continue;
  689.     }
  690.     if(*p=='(') par++;
  691.     add_token(arg,*p++);
  692.   }
  693. }
  694.  
  695. void stringize(tokenlist *new,tokenlist *src)
  696. {
  697.   int z,f,n;
  698.   int *p=src->tokens,*end=p+src->next;
  699. puts("1");
  700.   add_token(new,'"');
  701.   z=new->next;
  702.   add_token(new,0);
  703.   while(p<end){
  704. puts("2");
  705.     f=*p;
  706.     if(f==TKIDENTIFIER||f==TKNUMBER||f=='"'||f=='\''){
  707.       if(f=='"'){
  708.     add_token(new,'\\');
  709.     add_token(new,'"');
  710.     new->tokens[z]+=2;
  711.       }else if(f=='\''){
  712.     add_token(new,'\'');
  713.     new->tokens[z]++;
  714.       }
  715.       p++;
  716.       n=*p++;
  717.       while(--n>=0){
  718.     if((f=='"'||f=='\'')&&(*p=='\\'||*p=='"')){
  719.       add_token(new,'\\');
  720.       new->tokens[z]++;
  721.     }
  722.     add_token(new,*p++);
  723.     new->tokens[z]++;
  724.       }
  725.       continue;
  726.     }
  727. puts("3b");
  728.     add_token(new,*p++);
  729.     new->tokens[z]++;
  730.   }
  731. }
  732.  
  733. int expand(tokenlist *dest,tokenlist *old,tokenlist *scratch1,tokenlist *scratch2)
  734. {
  735.   int n,i,*p,*end;
  736.   int did_replace=0,notdone;
  737.   tokenlist *new=scratch1,*src=old,t1={0},t2={0};
  738.   do{
  739. puts("starting expand iteration");
  740.     notdone=0;
  741.     p=src->tokens;
  742.     end=p+src->next;
  743.     while(p<end){
  744.       if(*p==TKIDENTIFIER||*p==TKNUMBER||*p=='"'||*p=='\''){
  745.     if(*p==TKIDENTIFIER&&(n=find_macro(token2string(p)))!=0){
  746.       tokenlist *repl=¯o_table[n].repl;
  747.       if(!(macro_table[n].flags&NEED_PAREN)){
  748.         n=repl->next;
  749.         for(i=0;i<n;i++) add_token(new,repl->tokens[i]);
  750.         p+=p[1]+2;
  751.         did_replace=notdone=1;
  752.         continue;
  753.       }else if(p[p[1]+2]=='('){
  754.         tokenlist **args=mymalloc((macro_table[n].nargs+1)*sizeof(*args));
  755.         /*      tokenlist *scratch=mymalloc(sizeof(*scratch));*/
  756.         int *r,*end;
  757.         p+=p[1]+3;
  758.         for(i=0;i<macro_table[n].nargs;i++){
  759.           if(i!=0){
  760.         if(*p==',') p++; else puts(", expect");/*FIXME*/
  761.           }
  762.           args[i]=mymalloc(sizeof(**args));
  763.           args[i]->size=0;
  764.           args[i]->next=0;
  765.           args[i]->tokens=0;
  766.           p=get_macro_arg(args[i],p,0);
  767.           printf("arg %d:\n",i);
  768.           print_tokenlist(stdout,args[i]);
  769.         }
  770.         if(macro_table[n].flags&VARARG_MACRO){
  771.           args[i]=mymalloc(sizeof(**args));
  772.           args[i]->size=0;
  773.           args[i]->next=0;
  774.           args[i]->tokens=0;
  775.           if(*p==',') p++; else puts(", expect");/*FIXME*/
  776.           p=get_macro_arg(args[i],p,1);
  777.           printf("vararg:\n");
  778.           print_tokenlist(stdout,args[i]);
  779.         }
  780.         if(*p==')') p++; else puts(") expect");/*FIXME*/
  781.         
  782.         r=macro_table[n].repl.tokens;
  783.         end=r+macro_table[n].repl.next;
  784.         while(r<end){
  785.           if(*r==TKIDENTIFIER||*r==TKNUMBER||*r=='"'||*r=='\''){
  786.         n=r[1];
  787.         puts("insert idnt");
  788.         r+=2;
  789.         while(--n>=0) add_token(new,*r++);
  790.         continue;
  791.           }
  792.           if(*r=='#'){
  793.         r++;
  794.         if(*r!=TKMARG) {puts("huch?");ierror(0);/*FIXME*/}
  795.         r++;
  796.         n=*r++;
  797.         stringize(new,args[n]);
  798.         continue;
  799.           }
  800.           if(*r==TKMARG){
  801.         t1.next=t2.next=0;
  802.         expand(new,args[r[1]],&t1,&t2);
  803.         r+=2;
  804.         continue;
  805.           }
  806.           puts("insert other");
  807.           add_token(new,*r++);
  808.         }
  809.         
  810.         for(i=0;i<macro_table[n].nargs;i++) free(args[i]);
  811.         if(macro_table[n].flags&VARARG_MACRO) free(args[i]);
  812.         free(args);
  813.         did_replace=notdone=1;
  814.         continue;
  815.       }
  816.     }
  817.     add_token(new,*p++);
  818.     n=*p++;
  819.     add_token(new,n);
  820.     for(i=0;i<n;i++) add_token(new,*p++);
  821.       }else
  822.     add_token(new,*p++);
  823.     }
  824.     if(!notdone){
  825. puts("expand done, copying");
  826. print_tokenlist(stdout,new);
  827.       copy_tokenlist(dest,new);
  828. puts("copy done");
  829.     }else{
  830. puts("need another iteration");
  831.       src=new;
  832.       if(new==scratch1)
  833.     new=scratch2;
  834.       else
  835.     new=scratch1;
  836.       new->next=0;
  837.     }
  838.   }while(notdone);
  839.   return did_replace;
  840. }
  841.  
  842. #endif /* OBFUSCATOR */
  843.  
  844. main()
  845. {
  846.   int i,lastline=line,*p;
  847.   tokenlist tl={0},t2={0},t3={0},t4={0};
  848.   infile=include_file(0);
  849. #ifndef OBFUSCATOR  
  850.   hash_table=mymalloc(PP_HSIZE*sizeof(*hash_table));
  851.   for(i=0;i<PP_HSIZE;i++) hash_table[i]=0;
  852. #endif  
  853.   while(1){
  854.     tl.next=0;
  855.     while(!(i=get_next_token(&tl)));
  856.     add_token(&tl,TKEOL);
  857.     print_code(stdout,&tl);
  858.     if(i==EOF){
  859.     infile=close_file();
  860.     if(!infile) exit(0);
  861.     }
  862. #ifndef OBFUSCATOR
  863.     p=&tl.tokens[0];
  864.     while(*p==' ') p++;
  865.     if(*p=='#'&&(p[1]==TKIDENTIFIER||(p[1]==' '&&p[2]==TKIDENTIFIER))){
  866.       char *s;
  867.       p++;
  868.       if(*p!=TKIDENTIFIER) p++;
  869.       s=token2string(p);
  870.       if(!strcmp(s,"include")){
  871.     puts("include found");
  872.     *p=TKNUMBER; /* prevent expansion */
  873.     p+=2+p[1];
  874.     i=p-&tl.tokens[0];
  875.     t2.next=0;
  876.     t3.next=0;
  877.     t4.next=0;
  878.     expand(&t2,&tl,&t3,&t4);
  879.     p=&t2.tokens[i];
  880.     while(*p==' ') p++;
  881. printf("*p=%d\n",*p);
  882.     if(*p=='\"'){
  883.       s=token2string(p);
  884.       infile=include_file(s);
  885.       if(!infile) infile=close_file();
  886.       if(!infile) {exit(EXIT_FAILURE);/*FIXME*/}
  887.     }
  888.     
  889.     continue;
  890.       }else if(!strcmp(s,"define")){
  891.     puts("define found");
  892.     p+=2+p[1];
  893.     while(*p==' ') p++;
  894.     if(*p!=TKIDENTIFIER){
  895.       puts("#define needs ID");
  896.     }else{
  897.       char *mname;
  898.       int flags=0,nargs=0;
  899.       static char **pnames;
  900.       static int pnsize;
  901.  
  902.       s=token2string(p);
  903.       p+=2+p[1];
  904.       mname=mymalloc(strlen(s)+1);
  905.       strcpy(mname,s);
  906.       printf("id=%s\n",mname);
  907.       while(*p==' ') p++;
  908.       if(*p=='('){
  909.         puts("function-like");
  910.         p++;
  911.         while(*p==' ') p++;
  912.         while(*p==TKIDENTIFIER){
  913.           flags=0;
  914.           s=token2string(p);
  915.           p+=p[1]+2;
  916.           printf("parameter %s\n",s);
  917.           if(nargs>=pnsize){
  918.         pnsize+=PP_MSIZE;
  919.         pnames=myrealloc(pnames,pnsize*sizeof(*pnames));
  920.           }
  921.           for(i=0;i<nargs;i++)
  922.         if(!strcmp(pnames[i],s)) puts("double parameter");
  923.           pnames[nargs]=mymalloc(strlen(s)+1);
  924.           strcpy(pnames[nargs],s);
  925.           nargs++;
  926.           while(*p==' ') p++;
  927.           if(*p==','){ p++;flags=1;}
  928.           while(*p==' ') p++;
  929.         }
  930.         if(flags){
  931.           flags=NEED_PAREN;
  932.           if(*p==TKDDD){p++;flags|=VARARG_MACRO;}else puts(".../,");/*FIXME*/
  933.           while(*p==' ') p++;
  934.           if(*p==')') p++; else puts(") expect");/*FIXME*/
  935.         }else{
  936.           flags=NEED_PAREN;
  937.           if(*p==')') p++; else puts(") expect");/*FIXME*/
  938.         }
  939.       }
  940.       /*FIXME: # must be followed by parameter */
  941.       t2.next=0;
  942.       while(*p==' ') p++;
  943.       while(p<tl.tokens+tl.next&&*p!='\n'){
  944.         if(*p==TKIDENTIFIER){
  945.           s=token2string(p);
  946.           for(i=0;i<nargs;i++){
  947.         if(!strcmp(pnames[i],s)) break;
  948.           }
  949.           if(i<nargs||((flags&VARARG_MACRO)&&!strcmp("__VA_ARGS__",s))){
  950.         p+=p[1]+2;
  951.         add_token(&t2,TKMARG);
  952.         add_token(&t2,i);
  953.         continue;
  954.           }
  955.         }
  956.         add_token(&t2,*p++);
  957.       }
  958.       for(i=0;i<nargs;i++) free(pnames[i]);
  959.       i=new_macro(mname,flags,nargs,&t2);
  960.       add_macro(i);
  961.       printf("replacement-list for %s\n",mname);
  962.       print_tokenlist(stdout,&t2);
  963.     }
  964.       }
  965.     }else{
  966.       t2.next=0;
  967.       t3.next=0;
  968.       t4.next=0;
  969.       expand(&t2,&tl,&t3,&t4);
  970.       /*      print_tokenlist(stdout,&t2);*/
  971.       print_code(stdout,&t2);
  972.     }
  973. #endif /* OBFUSCATOR */    
  974.   }
  975. }
  976.